<template>
	<button
		:class="['v-button', `v-button--${size} v-button--${type} v-button--${model}`, { 'v-button--loading': loading, 'v-button--disabled': disabled, 'v-button--plain': plain }]"
		:disabled="disabled || loading"
		@click="handleClick"
	>
		<view v-if="loading" class="spinner"></view>
		<slot v-else></slot>
	</button>
</template>

<script setup lang="ts">
import { ref, onUnmounted, inject } from 'vue';
/**
 * v-button 按钮
 * type 				按钮类型 			默认值:default  可选值default默认、delete删除、succeed成功、info信息、warn警告
 * size 				按钮大小 			默认值:medium   可选值small小、medium中、large大
 * model 				按钮模式 			默认值:semicircle圆角按钮 可选值:square方形按钮、circle圆形按钮、border下边框按钮、text文本
 * disabled 			是否禁用 			true禁用  false不禁用
 * loading 				是否加载  			true加载  false不加载
 * plain				是否镂空				默认值:false		可选值:true镂空		false不镂空
 * stabilizationTime	防抖时间 			默认值0
 * intervalUpdateTime	间隔触发防抖时间
 * degressionTime		递减时间
 */
const props = defineProps({
	type: {
		type: String,
		default: 'default'
	},
	model: {
		type: String,
		default: 'semicircle',
		validator: (v: string) => ['semicircle', 'square', 'circle', 'border'].includes(v)
	},
	size: {
		type: String,
		default: 'medium',
		validator: (value: string) => ['small', 'medium', 'large'].includes(value)
	},
	disabled: {
		type: Boolean,
		default: false
	},
	loading: {
		type: Boolean,
		default: false
	},
	plain: {
		type: Boolean,
		default: false
	},
	stabilizationTime: {
		type: Number,
		default: 0
	},
	intervalUpdateTime: {
		type: Number,
		default: 1000
	},
	degressionTime: {
		type: Number,
		default: 1000
	}
});

const emit = defineEmits(['click', 'countdown']);

const config = inject<any>('config');
const clickTimer = ref<number | null>(null);
const countdownTimer = ref<number | null>(null);
const countdown = ref<number>(props.stabilizationTime);
const isCountingDown = ref(false);

onUnmounted(() => {
	if (clickTimer.value !== null) {
		clearTimeout(clickTimer.value);
	}
	if (countdownTimer.value !== null) {
		clearInterval(countdownTimer.value);
	}
});

const handleClick = (event: MouseEvent) => {
	if (!props.disabled && !props.loading && !isCountingDown.value) {
		if (clickTimer.value !== null) {
			clearTimeout(clickTimer.value);
		}
		if (countdownTimer.value !== null) {
			clearInterval(countdownTimer.value);
		}
		isCountingDown.value = true;
		countdown.value = props.stabilizationTime;

		emit('click', event);

		if (countdown.value > 0) {
			emit('countdown', { remaining: countdown.value, total: props.stabilizationTime });

			countdownTimer.value = window.setInterval(() => {
				if (countdown.value > 0) {
					countdown.value -= props.degressionTime;
					emit('countdown', { remaining: countdown.value, total: props.stabilizationTime });
				}

				if (countdown.value <= 0) {
					clearInterval(countdownTimer.value!);
					isCountingDown.value = false;
					emit('countdown', { remaining: 0, total: props.stabilizationTime });
				}
			}, props.intervalUpdateTime);
			clickTimer.value = window.setTimeout(() => {
				isCountingDown.value = false;
			}, props.stabilizationTime);
		} else {
			isCountingDown.value = false;
		}
	}
};
</script>

<style lang="scss">
.v-button {
	width: 150rpx;
	height: 50rpx;
	border: none;
	cursor: pointer;
	transition: all 0.3s;
	display: flex;
	align-items: center;
	justify-content: center;
	color: white;

	&:hover {
		opacity: v-bind('config.opacity.hover');
	}

	&:active {
		opacity: v-bind('config.opacity.click');
	}

	&--semicircle {
		border-radius: v-bind('config.borderRadius.semicircle');
	}

	&--square {
		border-radius: v-bind('config.borderRadius.square');
	}

	&--circle {
		border-radius: v-bind('config.borderRadius.circle');
	}

	&--border {
		border-radius: 0;
		border-bottom: 1rpx solid v-bind('config.border.color');
	}

	&--default {
		background-color: v-bind('config.backgroundColor.default') !important;
	}

	&--delete {
		background-color: v-bind('config.backgroundColor.delete') !important;
	}

	&--succeed {
		background-color: v-bind('config.backgroundColor.succeed') !important;
	}

	&--info {
		background-color: v-bind('config.backgroundColor.info') !important;
	}

	&--warn {
		background-color: v-bind('config.backgroundColor.warn') !important;
	}

	&--text {
		background-color: v-bind('config.backgroundColor.reversal') !important;
		color: v-bind('config.fontColor.text');
	}

	&--small {
		width: 120rpx;
		height: 50rpx;
		padding: 14rpx 2rpx;
		font-size: v-bind("config.fontSize.smallText");
	}

	&--medium {
		width: 150rpx;
		height: 60rpx;
		padding: 15rpx 0;
		font-size: v-bind("config.fontSize.mediumText");
	}

	&--large {
		width: 170rpx;
		height: 70rpx;
		padding: 20rpx 0;
		font-size: v-bind("config.fontSize.largeText");
	}

	&--disabled,
	&[disabled] {
		opacity: v-bind('config.opacity.disabled');
		cursor: not-allowed;
		color: v-bind('config.fontColor.reversal') !important;
	}

	&--loading {
		position: relative;
		overflow: hidden;
	}

	&--plain {
		background-color: transparent !important;
		border: 1rpx solid;
		color: currentColor;

		&.v-button--default {
			border-color:  v-bind("config.border.default");
			color: v-bind("config.fontColor.default");
		}

		&.v-button--delete {
			border-color:  v-bind("config.border.delete");
			color: v-bind("config.fontColor.delete");
		}

		&.v-button--succeed {
			border-color:  v-bind("config.border.succeed");
			color: v-bind("config.fontColor.succeed");
		}

		&.v-button--info {
			border-color: v-bind("config.border.info");
			color: v-bind("config.fontColor.info");
		}

		&.v-button--warn {
			border-color: v-bind("config.border.warn");
			color: v-bind("config.fontColor.warn");
		}

		&.v-button--text {
			border: none;
			color: v-bind("config.fontColor.text");
		}
	}

	.spinner {
		width: 20rpx;
		height: 20rpx;
		border: 1rpx solid;
		border-color: v-bind("config.border.color");
		border-radius: 50%;
		border-top-color: white;
		animation: spin 1s ease-in-out infinite;
	}

	@keyframes spin {
		to {
			transform: rotate(360deg);
		}
	}
}

uni-button:after {
	border: none;
}
</style>
